package com.treasure.mall.biz.remote.wx.impl;

import com.treasure.mall.biz.config.redis.RedisConfig;
import com.treasure.mall.biz.config.wechat.WeChatConfig;
import com.treasure.mall.biz.entity.wechat.WechatKeywordMessagePO;
import com.treasure.mall.biz.remote.wx.MessageUtil;
import com.treasure.mall.biz.remote.wx.ZbWxMpService;
import com.treasure.mall.biz.remote.wx.dto.WxToUser;
import com.treasure.mall.biz.service.core.user.WxSubscribeUserService;
import com.treasure.mall.biz.service.core.wechat.WechatKeywordMessageService;
import com.treasure.mall.zbq.common.ShaUtil;
import com.treasure.mall.zbq.common.exception.ApiException;
import com.treasure.mall.zbq.common.ienum.wx.WxMsgType;
import com.treasure.mall.zbq.common.oss.ResourceService;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.common.bean.menu.WxMenu;
import me.chanjar.weixin.common.bean.menu.WxMenuButton;
import me.chanjar.weixin.common.bean.result.WxMediaUploadResult;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.mp.api.WxMpMenuService;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.api.WxMpUserService;
import me.chanjar.weixin.mp.api.impl.WxMpMenuServiceImpl;
import me.chanjar.weixin.mp.api.impl.WxMpServiceImpl;
import me.chanjar.weixin.mp.api.impl.WxMpUserServiceImpl;
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutImageMessage;
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutTextMessage;
import me.chanjar.weixin.mp.bean.result.WxMpUser;
import me.chanjar.weixin.mp.bean.result.WxMpUserList;
import me.chanjar.weixin.mp.config.WxMpConfigStorage;
import me.chanjar.weixin.mp.config.impl.WxMpRedisConfigImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import redis.clients.jedis.JedisPool;

import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 *
 * <p>
 * +---------------------------------------------------------
 * * @package: com.treasure.mall.biz.remote.wx.impl
 * * @author: guomw (guomwchen@foxmail.com)
 * * @date: 2020/8/26 3:58 下午
 * * @since: V1.0.0
 * +---------------------------------------------------------
 * 注意：本内容仅限于内部传阅，禁止外泄以及用于其他的商业目的
 * 
 */
@Slf4j
@Service
public class ZbWxMpServiceImpl implements ZbWxMpService {
    private final static String token = "zbq123321zbq";
    private final static String API_URL = "https://api.weixin.qq.com/cgi-bin/menu/create?access_token=";
    private static volatile JedisPool jedisPool = null;
    @Autowired
    private RedisConfig redisConfig;
    @Autowired
    private WeChatConfig weChatConfig;
    @Autowired
    private WxSubscribeUserService subscribeUserService;
    @Autowired
    private ThreadPoolTaskExecutor threadPoolTaskExecutor;

    private static WxMpService wxMpService;
    @Autowired
    private WechatKeywordMessageService keywordMessageService;
    @Autowired
    private ResourceService resourceService;

    @PostConstruct
    public void init() {
        if (jedisPool == null) {
            jedisPool = redisConfig.redisPoolFactory();
        }
    }

    @Bean
    public WxMpService wxMpService() {
        if (wxMpService == null) {
            WxMpService _wxMpService = new WxMpServiceImpl();
            WxMpRedisConfigImpl wxMpRedisConfig = new WxMpRedisConfigImpl(jedisPool);
            wxMpRedisConfig.setAppId(weChatConfig.getWechatAppId());
            wxMpRedisConfig.setSecret(weChatConfig.getWechatAppSecret());
            wxMpRedisConfig.setAesKey(weChatConfig.getAesKey());
            wxMpRedisConfig.setToken(weChatConfig.getToken());
            WxMpConfigStorage wxMpConfigStorage = wxMpRedisConfig;

            _wxMpService.setWxMpConfigStorage(wxMpConfigStorage);
            wxMpService = _wxMpService;
            return _wxMpService;
        }
        return wxMpService;
    }

    @Override
    public WxMpService getService() {
        return wxMpService;
    }


    @Override
    public Boolean checkSignature(String signature, String timestamp, String nonce) {
        String tmpStr = ShaUtil.getSHA1(weChatConfig.getToken(), timestamp, nonce);
        if (tmpStr.equals(signature.toUpperCase())) {
//            this.createMenu();
            return true;
        }
        return false;
    }

    @Override
    public String messageHandle(HttpServletRequest request, HttpServletResponse response) {
        response.setCharacterEncoding("utf-8");
        Map<String, String> resultMap = MessageUtil.parseXml(request);
        //发送方帐号（一个OpenID）
//        String fromUserName = resultMap.get("FromUserName");
//        //开发者微信号
//        String toUserName = resultMap.get("ToUserName");
//        String msgType = resultMap.get("MsgType");
//        String event = resultMap.get("Event");
//        String content = resultMap.get("Content");
        WxToUser wxToUser = WxToUser.builder()
                .ToUserName(resultMap.get("ToUserName"))
                .FromUserName(resultMap.get("FromUserName"))
                .Content(resultMap.get("Content"))
                .MsgType(resultMap.get("MsgType"))
                .Event(resultMap.get("Event"))
                .build();
//        WxMpXmlMessage mpXmlMessage;
//        try {
//            mpXmlMessage = WxMpXmlMessage.fromXml(request.getInputStream());
//        } catch (IOException e) {
//            return "";
//        }

        if (wxToUser == null) {
            return "";
        }

        return messageHandle(wxToUser);

//        //订阅
//        if ("event".equals(mpXmlMessage.getMsgType()) && WxConsts.EventType.SUBSCRIBE.equals(mpXmlMessage.getEvent())) {
//            threadPoolTaskExecutor.execute(() -> this.setSubscribeUser(mpXmlMessage.getFromUser(), true));
//        }
//        //取消订阅
//        if ("event".equals(mpXmlMessage.getMsgType()) && WxConsts.EventType.UNSUBSCRIBE.equals(mpXmlMessage.getEvent())) {
//            threadPoolTaskExecutor.execute(() -> this.setSubscribeUser(mpXmlMessage.getFromUser(), false));
//        }
//        return "";
    }

    /**
     * 创建自定义菜单
     */
    @Override
    public void createMenu() {
        WxMpMenuService wxMpMenuService = new WxMpMenuServiceImpl(wxMpService());
        WxMenu wxMenu = new WxMenu();

        List<WxMenuButton> buttons = new ArrayList<>();
        WxMenuButton button = new WxMenuButton();
        button.setUrl("pages/index/index");
        button.setType("miniprogram");
        button.setName("数农商城");
        button.setAppId("wxc2764391ade782f2");
        button.setPagePath("pages/index/index");
        button.setKey("view");
        buttons.add(button);

        WxMenuButton button2 = new WxMenuButton();
        button2.setUrl("https://appgallery.huawei.com/#/app/C102580129");
        button2.setType("view");
        button2.setName("安卓APP");
        button2.setKey("view");
        buttons.add(button2);
        wxMenu.setButtons(buttons);


        WxMenuButton button3 = new WxMenuButton();
        button3.setUrl("https://apps.apple.com/cn/app/id1506697895");
        button3.setType("view");
        button3.setName("iOS下载");
        button3.setKey("view");
        buttons.add(button3);
        wxMenu.setButtons(buttons);

        try {
            wxMpMenuService.menuCreate(wxMenu);
        } catch (Exception e) {
            throw new ApiException(e.getMessage());
        }
    }

    /**
     * 设置关注用户
     *
     * @param openId
     */
    public void setSubscribeUser(String openId, boolean subscribe) {
        try {
            WxMpUser wxMpUser = new WxMpUser();
            wxMpUser.setOpenId(openId);
            if (subscribe) {
                WxMpUserService wxMpUserService = new WxMpUserServiceImpl(wxMpService());
                wxMpUser = wxMpUserService.userInfo(openId);
            }
            if (wxMpUser != null) {
                subscribeUserService.setSubscribeUser(wxMpUser, subscribe);
            }
        } catch (WxErrorException e) {
        }
    }

    /**
     * 初始化公众号关注用户
     */
    @Override
    public void initSubScribeUsers() {
        try {
            WxMpUserService wxMpUserService = new WxMpUserServiceImpl(wxMpService());

            WxMpUserList list = wxMpUserService.userList(null);
            if (list == null) {
                return;
            }
            List<WxMpUser> wxMpUsers = wxMpUserService.userInfoList(list.getOpenids());

            if (wxMpUsers == null || wxMpUsers.size() == 0) {
                return;
            }
            //保存关注用户
            wxMpUsers.forEach(wxMpUser -> subscribeUserService.setSubscribeUser(wxMpUser, true, false));
        } catch (Exception e) {
        }
    }

    /**
     * 消息回复
     *
     * @param mpXmlMessage
     * @return
     */
    private String messageHandle(WxToUser mpXmlMessage) {
        String outMessage = "";
        switch (mpXmlMessage.getMsgType()) {
            case WxConsts.XmlMsgType.TEXT:
                outMessage = outMessage(mpXmlMessage);
                break;
            case WxConsts.XmlMsgType.EVENT:
                //订阅
                if (WxConsts.EventType.SUBSCRIBE.equals(mpXmlMessage.getEvent())) {
                    threadPoolTaskExecutor.execute(() -> this.setSubscribeUser(mpXmlMessage.getFromUserName(), true));
                }
                //取消订阅
                if (WxConsts.EventType.UNSUBSCRIBE.equals(mpXmlMessage.getEvent())) {
                    threadPoolTaskExecutor.execute(() -> this.setSubscribeUser(mpXmlMessage.getFromUserName(), false));
                }
                break;
            default:
                break;
        }
        return outMessage;
    }

    /**
     * 回复图片信息
     *
     * @param mpXmlMessage
     * @return
     */
    public String outMessage(WxToUser mpXmlMessage) {
        WechatKeywordMessagePO message = keywordMessageService.findByKeyword(mpXmlMessage.getContent());
        if (message == null) {
            return "";
        }
        /**
         * 回复文本消息
         */
        if (message.getMsgType().equals(WxMsgType.TEXT)) {
            WxMpXmlOutTextMessage textMessage = WxMpXmlOutTextMessage.TEXT()
                    .fromUser(mpXmlMessage.getToUserName())
                    .toUser(mpXmlMessage.getFromUserName())
                    .content(message.getContent())
                    .build();
            return textMessage.toEncryptedXml(wxMpService().getWxMpConfigStorage());
        }
        //回复图片消息
        if (message.getMsgType().equals(WxMsgType.IMAGE)) {
            WxMediaUploadResult result;
            try {
                int index = message.getUrl().lastIndexOf(".");
                String fileType = message.getUrl().substring(index + 1);
                result = wxMpService().getMaterialService().mediaUpload(WxConsts.MaterialType.IMAGE, fileType, resourceService.getInputStream(message.getUrl()));
            } catch (Exception e) {
                return "";
            }
            if (result != null) {
                WxMpXmlOutImageMessage image = WxMpXmlOutImageMessage.IMAGE()
                        .fromUser(mpXmlMessage.getToUserName())
                        .toUser(mpXmlMessage.getFromUserName())
                        .mediaId(result.getMediaId())
                        .build();
                return image.toEncryptedXml(wxMpService().getWxMpConfigStorage());
            }
        }
        return "";
    }

}
